package com.tzl.filter;

import com.tzl.properties.SecurityGatewayProperties;
import com.tzl.util.JwtUtil;
import com.tzl.utils.ResponseUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

@Component
@Slf4j
public class HzitGlobalFilter implements GlobalFilter, Ordered {
	@Autowired
	private SecurityGatewayProperties gatewayProperties;
	@Autowired
	private StringRedisTemplate redisTemplate;
	//过滤请求，检查Token的有效性
	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		List<String> whites = gatewayProperties.getWhites(); // 获取白名单路径
		ServerHttpRequest request = exchange.getRequest();
		ServerHttpResponse response = exchange.getResponse();
		ServerHttpRequest.Builder mutate = request.mutate();
		String path = request.getURI().getPath();
		// 路径在白名单中，不进行Token校验
		if (whites.contains(path)) {
			return chain.filter(exchange);
		}
		// 获取Authorization头中的Token
		String authorization = request.getHeaders().getFirst("Authorization");
		String token = authorization.replace("Bearer ", "");
		// 解析Token，获取Claims
		Claims claims = JwtUtil.parseToken(token);
		if (claims == null) {
			return ResponseUtil.webFluxResponseWriter(response, "解析token失败！");
		}
		// 获取用户的唯一标识符(user_key)
		String uuid = claims.get("user_key") + "";
		String key = getKey(uuid); // 获取Redis中存储Token的Key
		// 判断Redis中是否存在该Token
		Boolean hasKey = redisTemplate.hasKey(key);
		if (!hasKey) {
			return ResponseUtil.webFluxResponseWriter(response, "登录失败！");
		}
		// 继续处理请求
		return chain.filter(exchange.mutate().request(mutate.build()).build());
	}
	//获取Token对应的Redis Key
	private String getKey(String token) {
		return "login_tokens:" + token;
	}
	//设置过滤器执行顺序
	@Override
	public int getOrder() {
		return -100;
	}
}
